#include "e2d/ui/CustumFileSystemLayer.h"
#include "e2d/ui/Utils.h"
#include "sysx/System.h"

e2d::CustumFileSystemLayer::CustumFileSystemLayer()
    :fxcc::imgui::FileSystemLayer(".")
{

    OnLoadPath();
    SetDirPath(m_CurrentPathStr);

    OnLoad();
}

void e2d::CustumFileSystemLayer::LoadIconTexture(const std::string& path, fxcc::FileType type)
{
    fxcc::graph::common::Texture2DJack::Desc desc2;
    desc2.SetPath(path);
    
    m_Textures[(int)type] = std::make_shared<fxcc::graph::opengl3::Texture2DJack>(desc2);

}

void e2d::CustumFileSystemLayer::LoadFilesInDir(fxcc::Dir* inst)
{
    for (auto file : inst->m_Files)
    {
        file->m_Icon = m_Textures[0]->GetTextureId();
        std::string suffix = file->m_Suffix;
        if (!suffix.empty()) {
        }
    }

    for (auto dir : inst->m_Dirs)
    {
        dir->m_Icon = m_Textures[(int)fxcc::FileType::_Dir_]->GetTextureId();
        LoadFilesInDir(dir.get());
    }
}

void e2d::CustumFileSystemLayer::OnLoad()
{


    IntoChangeDir();

    static auto& am = fxcc::AssertManager::Inst();
    LoadIconTexture(am.GetFile("icon/file.png"), fxcc::FileType::_File_);
    LoadIconTexture(am.GetFile("icon/folder.png"), fxcc::FileType::_Dir_);

    LoadFilesInDir(m_Dir.get());

}

void e2d::CustumFileSystemLayer::OnRefresh()
{
    m_CurrentDir->Load();
    OnLoad();
}

void e2d::CustumFileSystemLayer::OnWindowContextItem()
{
    auto& sg = e2d::State::Inst();


    if (ImGui::BeginPopupContextWindow(""))
    {
        if (ImGui::BeginMenu("Add"))
        {
            if (ImGui::MenuItem("EffectDesc"))
            {
                AddEffectsDescFileDefault();
                OnRefresh();
            }
            ImGui::EndMenu();
        }

        if (ImGui::MenuItem("Refresh"))
        {
            OnRefresh();

        }

        if (ImGui::MenuItem("Edit"))
        {
            auto files = GetAllFilesSelected();
            for (const auto& file : files)
            {
                EditFile(file);
            }

        }

        if (ImGui::MenuItem("Open in explore"))
        {
            
            if(m_CurrentDir)
            { 
                sysx::System::RevealDir(m_CurrentDir->m_AbsolutePath);
            }
        }
        ImGui::EndPopup();
    }
}

void e2d::CustumFileSystemLayer::ViewFunc()
{
    if (ImGui::TreeNode("tools"))
    {
        ImGui::SetNextItemWidth(200);
        m_Editor.EditInst<std::string>("New File", m_NewFileName);
        bool btnCS = ImGui::Button("C#");
        ImGui::SameLine();
        bool btnActor = ImGui::Button("Actor");

        if (btnActor)
        {
            std::string fileName = m_NewFileName + ".actor";
            fs::path _fullPath = fs::path(m_CurrentDir->m_RelativePath) / fs::path(fileName);

            auto inst = std::make_shared<e2d::AnimationController>();
            fxcc::yml::Serializer serializer;
            serializer.EncodePath<e2d::AnimationController>(_fullPath.string(), *inst);

        }
        if (btnCS)
        {
            std::string context = e2d::TextWriter::CSharpCode(m_NewFileName);
            std::string fileName = m_NewFileName + ".cs";
            fs::path _p = fs::path(m_CurrentDir->m_RelativePath) / fileName;;
            fxcc::FileUtil::Write(_p.string(), context);
        }

        if (btnCS || btnActor)
        {
            m_CurrentDir->Load();
            OnLoad();
        }
        ImGui::TreePop();

    }

    TableView();
}


void e2d::CustumFileSystemLayer::Grid(fxcc::File* file)
{
    ImGui::PushID(file);
    auto& io = ImGui::GetIO();

    ImGui::TableNextColumn();
    ImGui::SetNextItemWidth(m_ColWidth);

    ImVec4 bg_Col = file->m_Selected ? ImVec4(0, 0.5, 0.5, 1.0f) : ImVec4(0, 0, 0, 0);
    bool flag = ImGui::ImageButton(file->m_FileName.c_str(), file->m_Icon, m_LabelSize, ImVec2(0, 0), ImVec2(1, 1), bg_Col);
    GetItemPos(file->m_StartPos, file->m_EndPos);

    bool isRightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right);
    bool isItemHover = ImGui::IsItemHovered();
    bool isDoubleClicked = ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left);
    bool isItemClicked = ImGui::IsItemClicked();
    if (isItemClicked && isDoubleClicked)
    {
        ztclog::info("item %s clicked", file->m_RelativePath.c_str());
        EditFile(file);
    }

    if (flag || (isItemHover && isRightClick))
    {
        if (!io.KeyCtrl)
        {
            m_CurrentDir->UnSelecteAll();
        }
        file->m_Selected = !file->m_Selected;
    };

    if (file->m_IsDir)
    {
        bool doubleClicked = ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left);
        bool itemClicked = ImGui::IsItemClicked();

        if (itemClicked && doubleClicked)
        {
            m_SelectedDir = reinterpret_cast<fxcc::Dir*>(file);
            m_ChangeFlag = true;
        }
    }

    if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
    {
        ImGui::SetDragDropPayload("File", file, sizeof(fxcc::File));
        ImGui::Text(file->m_FileName.c_str());
        ImGui::EndDragDropSource();
    }

    ImGui::Text(file->m_FileName.c_str());

    ImGui::PopID();
}

std::vector<fxcc::File*> e2d::CustumFileSystemLayer::GetAllFilesSelected()
{
     std::vector<fxcc::File*> res;
     for (auto file : m_CurrentDir->m_Files)
     {
         if (file->m_Selected)
         {
             res.push_back(file.get());
         }
     }
     return res;
}

void e2d::CustumFileSystemLayer::EditFile(fxcc::File* file)
{
    ztclog::info("handle file %s", file->m_RelativePath.c_str());

    auto& sg = e2d::State::Inst();

    switch (file->m_FileType)
    {
    case fxcc::FileType::_Mat_:
    {
        ztclog::info("edit _Mat_ file");
        sg.m_EditMaterialFlag = true;
        sg.m_EditMaterialPath = file->m_RelativePath;

        break;
    }
    case fxcc::_Anim_:
    {
        ztclog::info("edit _Anim_ file");
        break;
    }
    case fxcc::_Effects_:
    {
        ztclog::info("edif effects %s", file->m_RelativePath.c_str());
        sg.m_EditEffectsFlag = true;
        sg.m_EditEffectsPath = file->m_RelativePath;
        break;
    }
    case fxcc::_Actor_:
    {
        ztclog::info("edit _Actor file");

        sg.m_EditActorFlag = true;
        sg.m_EditActorPath = file->m_RelativePath;

        break;
    }
    default:
        break;
    }
}

void e2d::CustumFileSystemLayer::OnDestroy()
{
    OnSavePath();
}

void e2d::CustumFileSystemLayer::OnSavePath()
{
    fxcc::FileUtil::Write(CH_Path(), m_CurrentDir->m_RelativePath);
}

void e2d::CustumFileSystemLayer::OnLoadPath()
{
    m_CurrentPathStr = fxcc::FileUtil::ReadFileToString(CH_Path());
}

std::string e2d::CustumFileSystemLayer::CH_Path()
{
    return ".cache/fsLayer.imgui";
}

bool e2d::CustumFileSystemLayer::AddEffectsDescFile(const std::string& fn)
{
    fxcc::yml::Serializer ymlser;
    e2d::EffectsDesc desc;
    return ymlser.EncodePath<e2d::EffectsDesc>(fn, desc);
}

bool e2d::CustumFileSystemLayer::AddEffectsDescFileDefault()
{
    std::string _p = this->m_CurrentDir->GetFileWithoutRepeat("default", ".effects");
    return AddEffectsDescFile(_p);

}


void e2d::CustumFileSystemLayer::TableView()
{
    auto& io = ImGui::GetIO();

    int flag = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;

    int numCol = (m_WindowSize.x - m_Padding.x) / m_ColWidth;

    if (numCol == 0)
    {
        numCol = 1;
    }
    int totalSize = m_CurrentDir->Count();

    for (auto indexDir : m_IndexDirs)
    {
        bool btn = ImGui::Button(indexDir->m_FileName.c_str());
        ImGui::SameLine();
        ImGui::Text("/");
        ImGui::SameLine();

        if (btn)
        {
            m_ChangeFlag = true;
            m_SelectedDir = indexDir;

        }
    }
    ImGui::Text("");

    if (ImGui::BeginTable("IconTable", numCol, 0)) {

        for (auto dir : m_CurrentDir->m_Dirs)
        {
            Grid(dir.get());
        }

        for (auto file : m_CurrentDir->m_Files)
        {
            Grid(file.get());
        }

        ImGui::EndTable();
    }

    if (this->m_IsFocused)
    {
        if (ImGui::IsMouseClicked(3))
        {
            m_SelectedDir = m_CurrentDir->m_Parent;
            m_ChangeFlag = true;
        }

        if (ImGui::IsKeyDown(ImGuiKey_A) && io.KeyCtrl)
        {
            m_CurrentDir->SetSelectAll(true);
        }
        if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
        {
            if (IsMouseOnWindow() && !ImGui::IsAnyItemHovered())
            {
                m_CurrentDir->UnSelecteAll();
            }
        }
    }

    OnWindowContextItem();
}
